﻿///
/// Pamela.Logic.Imps
///
namespace Pamela.Logic.Imps.Mvc
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Text;

    using Pamela.Logic.Helpers;
    using Pamela.Logic.Imps.Base;
    using Pamela.Logic.Properties;

    /// <summary>
    /// ControllerBuilder class
    /// </summary>
    internal class MvcControllerBuilder : BaseBuilder
    {
        /// <summary>
        /// The data model extracted from the shared DLL assembly
        /// </summary>
        private Type modelType;

        /// <summary>
        /// Initializes a new instance of the ControllerBuilder class
        /// </summary>
        /// <param name="assembly">The shared DLL assembly</param>
        /// <param name="info">Builder  object containing all the info to necessary perform the scaffolding operation</param>
        public MvcControllerBuilder(Assembly assembly, BuilderInfo info, string layerName)
            : base(assembly, info, layerName, "controlleragg.template")
        {
            this.modelType = this.assembly.GetType(string.Format("{0}.Shared.Models.{1}", this.builderInfo.RootNamespace, this.builderInfo.SelectedModel));
        }
        
        /// <summary>
        /// Builds the controller file based on the BuilderInfo provided
        /// </summary>
        public override void Build()
        {
            using (StreamReader template = new StreamReader(this.templatePath))
            using (StreamWriter output = new StreamWriter(this.builderInfo.ControllerDestinationFile))
            {
                while (template.Peek() >= 0)
                {
                    string buffer = template.ReadLine();

                    buffer = buffer.Replace(Resources.BusinessLayerNamespace, builderInfo.BusinessLayerNamespace);
                    buffer = buffer.Replace(Resources.DataLayerNamespace, builderInfo.DataLayerNamespace);
                    buffer = buffer.Replace(Resources.Namespace, builderInfo.RootNamespace);
                    buffer = buffer.Replace(Resources.SelectedModel, builderInfo.SelectedModel);
                    buffer = buffer.Replace(Resources.SelectedModelSmallCaps, builderInfo.SelectedModel.ToLower());
                    buffer = buffer.Replace(Resources.Entity, pluralizationService.Pluralize(builderInfo.SelectedModel));
                    buffer = buffer.Replace(Resources.ViewBagAdd, this.CreateAddActionMethodViewBagTemplate());
                    buffer = buffer.Replace(Resources.ViewBagEdit, this.CreateEditActionMethodViewBagTemplate());
        
                    output.WriteLine(buffer);
                }
            }
        }

        /// <summary>
        /// Creates the view bag string for add action method
        /// </summary>
        /// <returns>View bag string template</returns>
        private string CreateAddActionMethodViewBagTemplate()
        {
            var result = new StringBuilder();

            foreach (var property in this.modelType.GetProperties())
            {
                if (property.GetMethod.IsVirtual && !property.PropertyType.IsGenericType)
                {
                    result.Append(string.Format("var {0}Service = new {1}Service();\r\n\t\t\t", property.Name.ToLower(), property.Name));
                    result.Append(string.Format(@"ViewBag.{0}Id = new SelectList({0}Service.List(), ""{1}Id"", ""{1}Name"");", property.Name.ToLower(), property.Name));
                }
            }

            return result.ToString();
        }

        /// <summary>
        /// Creates the view bag string for edit action method
        /// </summary>
        /// <returns>View bag string template</returns>
        private string CreateEditActionMethodViewBagTemplate()
        {
            var result = new StringBuilder();

            foreach (var property in this.modelType.GetProperties())
            {
                if (property.GetMethod.IsVirtual && !property.PropertyType.IsGenericType)
                {
                    result.Append(string.Format("var {0}Service = new {1}Service();\r\n\t\t\t\t", property.Name.ToLower(), property.Name));
                    result.Append(string.Format(@"ViewBag.{0}Id = new SelectList({0}Service.List(), ""{1}Id"", ""{1}Name"", model.{1}Id);", property.Name.ToLower(), property.Name));
                }
            }

            return result.ToString();
        }
    }
}
